#pragma once

#include "Socket.hpp"
#include <signal.h>
#include <functional>
#include "InetAddr.hpp"

using callback_t = std::function<std::string(std::string &)>;

class Tcpserver
{
public:
    Tcpserver(uint16_t port, callback_t cb)
        : _port(port), _listensocket(std::make_unique<TcpSocket>()), _cb(cb)
    {
        _listensocket->BuildListenSocketMethod(_port);
    }

    void HandlerRequest(std::shared_ptr<Socket> sockfd, InetAddr addr)
    {
        // 读取直到完整 HTTP 头（\r\n\r\n）或连接关闭
        std::string inbuffer;
        while (true)
        {
            bool ok = sockfd->Recv(&inbuffer, 4096);
            if (!ok)
                break; // 连接关闭或出错
            if (inbuffer.find("\r\n\r\n") != std::string::npos)
                break; // 收到完整头部
            // 继续读取直到头部结束或超时/关闭
        }

        if (!inbuffer.empty())
        {
            LOG(LogLevel::INFO) << addr.ToString() << "# " << inbuffer;

            // 处理收到的数据
            std::string ret_str = _cb(inbuffer); // 检查 序列化 解包

            sockfd->Send(ret_str);
        }
        else
        {
            LOG(LogLevel::WARNING) << "empty request or read error from client " << addr.ToString() << ", sockfd: " << sockfd->GetSockFd();
        }

        sockfd->CloseSocket();
    }
    void Run()
    {
        signal(SIGCHLD, SIG_IGN);

        while (true)
        {
            // 方法 1
            InetAddr clientaddr;
            auto sockfd = _listensocket->Accept(&clientaddr);
            if (sockfd == nullptr)
            {
                // Accept 失败（如临时资源不足或信号打断），避免忙循环
                sleep(1);
                continue;
            }
            LOG(LogLevel::INFO) << "获取新链接成功, sockfd is : " << sockfd->GetSockFd() << " client addr: " << clientaddr.ToString();

            // 方法 2
            // std::string *peerip;
            // uint16_t *peerport;
            // _listensocket->AcceptConnection(peerip, peerport);
            if (fork() == 0)
            {
                // 子进程
                _listensocket->CloseSocket();
                HandlerRequest(sockfd, clientaddr);
                exit(0);
            }
            sockfd->CloseSocket();
        }
    }
    ~Tcpserver()
    {
    }

private:
    uint16_t _port;
    std::unique_ptr<Socket> _listensocket;
    callback_t _cb;
};